package com.pig4cloud.pig.ads.gdt.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.pig4cloud.pig.ads.gdt.service.GdtAccesstokenService;
import com.pig4cloud.pig.ads.gdt.service.GdtCustomAudiencesService;
import com.pig4cloud.pig.ads.gdt.service.GdtSelectListService;
import com.pig4cloud.pig.ads.service.TtAccesstokenService;
import com.pig4cloud.pig.ads.utils.OEHttpUtils;
import com.pig4cloud.pig.api.gdt.dto.*;
import com.pig4cloud.pig.api.gdt.entity.GdtCustomAudiences;

import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.api.util.Constants;
import com.pig4cloud.pig.api.util.MapUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class GdtSelectListServiceImpl implements GdtSelectListService {

	@Autowired
    GdtAccesstokenService gdtAccesstokenService;

	@Autowired
    TtAccesstokenService ttAccesstokenService;

	@Autowired
    GdtCustomAudiencesService gdtCustomAudiencesService;

	@Autowired
	StringRedisTemplate stringRedisTemplate;
	@Value("${gdt_scene_spec_tags_url:https://api.e.qq.com/v1.3/scene_spec_tags/get}")
	String sceneSpecTagsUrl;

	@Override
	public R czSite(String advertiserId, Integer page, Integer pageSize) {
		Map<String, Object> reqData = new HashMap<String, Object>();
		reqData.put("advertiser_id", advertiserId);
		reqData.put("status","SITE_ONLINE");
		if (page!=null)
			reqData.put("page", page);

		if (pageSize != null)
			reqData.put("page_size", pageSize);
		else
			reqData.put("page_size", 300);


		String token = ttAccesstokenService.fetchAccesstoken(advertiserId);		// this.getAccesstoken(advertiserId);

		//调用头条接口
		String resultStr = OEHttpUtils.doGet("https://ad.oceanengine.com/open_api/2/tools/site/get/", reqData, token);

		//结果为null，当做失败
		if (StringUtils.isBlank(resultStr))
			return R.failed("从toutiao获取失败:resultStr is blank");

		JSONObject obj = JSON.parseObject(resultStr);
		if (!obj.getInteger("code").equals(0)){	//同步失败
			return R.failed("从toutiao获取失败:" + obj.getString("message"));
		}else{
			JSONObject data = obj.getJSONObject("data");
			JSONArray list = data.getJSONArray("list");
			for (int i=0; i<list.size(); i++){
				JSONObject item = list.getJSONObject(i);
				item.put("jz_url","https://www.chengzijianzhan.com/tetris/page/" + item.getString("siteId") );
			}
			return R.ok(data, "获取成功");
		}
	}

	@Override
	public R industryList(String advertiserId) {

		InputStream is = this.getClass().getClassLoader().getResourceAsStream("industry.json");
		byte[] getData = new byte[0];
		try {
			getData = readInputStream(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String content = new String(getData);

		JSONArray data =  JSONObject.parseArray(content);

		return R.ok(data, "获取成功");
	}

	@Override
	public R maritalStatus() {
		String content = this.fileContentByName("marital_status.json");

		JSONArray data =  JSONObject.parseArray(content);
		return R.ok(data, "获取成功");
	}

	@Override
	public R workingStatus() {
		String content = this.fileContentByName("working_status.json");

		JSONArray data =  JSONObject.parseArray(content);
		return R.ok(data, "获取成功");
	}

	@Override
	public R customAudience(Page page, String accountId, String searchName) {
		QueryWrapper<GdtCustomAudiences> queryWrapper = new QueryWrapper<>();
		//推广账户Id
		if (StringUtils.isNotBlank(accountId)) {
			//多个账户之间逗号分隔
			queryWrapper.in("account_id", accountId);
		}
		//搜索名称/ID
		if (StringUtils.isNotBlank(searchName)) {
			queryWrapper.like("name", searchName).or().like("audience_id", searchName);
		}
		//状态
		//queryWrapper.eq("status", "SUCCESS");

		//根据创建时间降序
		queryWrapper.orderByDesc("created_time");

		return R.ok(gdtCustomAudiencesService.list(queryWrapper));
	}

	@Override
	public R userOs() {
		String content = this.fileContentByName("user_os.json");

		JSONArray data =  JSONObject.parseArray(content);
		return R.ok(data, "获取成功");
	}

	@Override
	public R behaviorInterest(String accountId, String tag){
		String redisKey = this.getRedisKey(accountId, tag);
		String redisKeyTransed = null;

		if (StringUtils.isNotBlank(redisKey)){
			redisKeyTransed = redisKey + "_TRANSED";

			String transedStr = stringRedisTemplate.opsForValue().get(redisKeyTransed);
			if (StringUtils.isNotBlank(transedStr)){
				return R.ok(JSON.parseArray(transedStr));
			}
		}

		String resultStr = this.fetchFromGdt(accountId, tag);

		//结果为null，当做失败
		if (StringUtils.isBlank(resultStr))
			return R.failed("从第三方获取失败:resultStr is null");

		JSONObject obj = JSON.parseObject(resultStr);
		if (!obj.getInteger("code").equals(0)){
			String msg = obj.getString("message_cn");
			return R.failed("从第三方获取失败:" + msg);
		}



		//处理数据
		String dataStr = obj.getJSONObject("data").getString("list");
		//获取成功，缓存数据
		if (StringUtils.isNotBlank(redisKey))
			stringRedisTemplate.opsForValue().set(redisKey, dataStr);

		List<GdtTargetingTags> dataList = JSON.parseArray(dataStr, GdtTargetingTags.class);
		List<GdtTargetingTags> leveledData = dealLevels(dataList);

		//对关键词id做特殊处理
		switch (tag){
			case "BEHAVIOR_SYSTEMATIC" :
			case "BEHAVIOR_INDUSTRY_HOT" :
			case "INTEREST_SYSTEMATIC":
			case "INTEREST_INDUSTRY_HOT" :
				for (int i =0 ;i < leveledData.size(); i++){
					GdtTargetingTags item = leveledData.get(i);
					item.setId(BigInteger.valueOf(i+1));
				}
				break;
			default:
				break;
		}

		//缓存处理后的数据
		if (StringUtils.isNotBlank(redisKeyTransed))
			stringRedisTemplate.opsForValue().set(redisKeyTransed, JSON.toJSONString(leveledData));

		//若同步成功	跟更新状态到数据库
		return R.ok(leveledData);
	}

	//婚恋育儿状态
	//工作状态
	//操作系统版本

	//设备品牌型号

	@Override
	public R getParentLevels(String accountId, String ids, String tag) {
		String redisKey = null;//Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag + tag.contains("");

		final List<GdtTargetingTagsStringId> dataList = new ArrayList<>();
		switch (tag){
			case "BEHAVIOR_SYSTEMATIC" :
			case "BEHAVIOR_INDUSTRY_HOT" :
			case "INTEREST_SYSTEMATIC":
			case "INTEREST_INDUSTRY_HOT" :
				return R.ok(JSON.parseArray(ids),"该列表不是树形");
			case "BEHAVIOR_CATGORY" :
			case "INTEREST_CATGORY":
			case "INTENTION" :
			case "BUSINESS_INTEREST" :
			case "DEVICE_BRAND_MODEL" :
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag;

				String dataStr = stringRedisTemplate.opsForValue().get(redisKey);
				if (StringUtils.isBlank(dataStr)){
					String resultStr = this.fetchFromGdt(accountId, tag);

					if (StringUtils.isBlank(resultStr))
						return R.failed("redis不存在该数据，且从广点通获取失败:" + tag);

					JSONObject obj = JSON.parseObject(resultStr);
					if (!obj.getInteger("code").equals(0)){
						return R.failed(String.format("redis不存在%s数据，且从广点通获取失败:%s", tag, resultStr));
					}

					dataStr = obj.getJSONObject("data").getString("list");
					stringRedisTemplate.opsForValue().set(redisKey, dataStr);
				}

				//解析redis中的数据
				dataList.addAll(JSON.parseArray(dataStr, GdtTargetingTagsStringId.class));
				break;
			case "REGION":
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag;

				String regionStr = stringRedisTemplate.opsForValue().get(redisKey);
				if (StringUtils.isBlank(regionStr))
					return R.failed("redis获取商圈数据失败");
				dataList.addAll(JSON.parseArray(regionStr, GdtTargetingTagsStringId.class));
				break;
			case "BUSINESS_DISTRICT" :
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag;
				String busDistrictStr = stringRedisTemplate.opsForValue().get(redisKey);
				if (StringUtils.isBlank(busDistrictStr))
					return R.failed("redis获取商圈数据失败");
				dataList.addAll(JSON.parseArray(busDistrictStr, GdtTargetingTagsStringId.class));

				String resionStr = stringRedisTemplate.opsForValue().get(Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + "REGION");
				if (StringUtils.isBlank(resionStr))
					return R.failed("redis获取地域数据失败");
				List<GdtTargetingTagsStringId> busDistricList = JSON.parseArray(resionStr, GdtTargetingTagsStringId.class);
				dataList.addAll(busDistricList);
				break;

			case "MARITAL_STATUS" :
			case "USER_OS" :
			case "WORKING_STATUS" :
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag;
				String content = stringRedisTemplate.opsForValue().get(redisKey);
				if (StringUtils.isBlank(content)){
					String fileName = tag.toLowerCase()+ "_simple.json";
					content = this.fileContentByName(fileName);

					if (StringUtils.isBlank(content))
						return R.failed("获取数据失败:" + tag);

					stringRedisTemplate.opsForValue().set(redisKey, content);
				}

				List<GdtTargetingTagsStringId> listFromFile = JSON.parseArray(content, GdtTargetingTagsStringId.class);
				dataList.addAll(listFromFile);
				break;
			default:
				redisKey = null;
		}

		if (dataList!= null && dataList.size()>0){

			List<String> idArr = JSON.parseArray(ids, String.class);

			List<String> leveledIds = dataList.stream().filter(item -> idArr.contains(String.valueOf(item.getId())))
					.map(item -> {
						String level_0 = String.valueOf(item.getId());
						String level_1 = null;
						String level_2 = null;
						String level_3 = null;
						String level_4 = null;

						StringBuilder sb = new StringBuilder();

						List<GdtTargetingTagsStringId> level_1List  = dataList.stream().filter(jtem -> jtem.getId().equals(item.getParent_id())).collect(Collectors.toList());
						if (level_1List.size() < 1) return level_0;
						GdtTargetingTagsStringId jtem = level_1List.get(0);
						level_1 = jtem.getId();

						List<GdtTargetingTagsStringId> level_2List  = dataList.stream().filter(ktem -> ktem.getId().equals(jtem.getParent_id())).collect(Collectors.toList());
						if (level_2List.size() < 1) return String.format("%s,%s",level_1, level_0);
						GdtTargetingTagsStringId ktem = level_2List.get(0);
						level_2 = ktem.getId();

						List<GdtTargetingTagsStringId> level_3List  = dataList.stream().filter(ltem -> ltem.getId().equals(ktem.getParent_id())).collect(Collectors.toList());
						if (level_3List.size() < 1) return String.format("%s,%s,%s", level_2, level_1, level_0);
						GdtTargetingTagsStringId ltem = level_3List.get(0);
						level_3 = ltem.getId();

						List<GdtTargetingTagsStringId> level_4List  = dataList.stream().filter(mtem -> mtem.getId().equals(ltem.getParent_id())).collect(Collectors.toList());
						if (level_4List.size() < 1) return String.format("%s,%s,%s,%s", level_3, level_2, level_1, level_0);
						GdtTargetingTagsStringId mtem = level_4List.get(0);
						level_4 = mtem.getId();
						return String.format("%s,%s,%s,%s,%s", level_4, level_3, level_2, level_1, level_0);
					}).collect(Collectors.toList());

			return R.ok(leveledIds);


/*			String resultStr = stringRedisTemplate.opsForValue().get(redisKey);

			if (StringUtils.isBlank(resultStr)){
				this.fetchFromGdt(accountId, tag);
			}

			JSONObject obj = JSON.parseObject(resultStr);
			if (!obj.getInteger("code").equals(0)){
				return R.failed("redis中缓存的数据状态不对,code:" + obj.getInteger("code"));
			}

			//解析redis中的数据
			String dataStr = obj.getJSONObject("data").getString("list");
			List<GdtTargetingTags> dataList = JSON.parseArray(dataStr, GdtTargetingTags.class);*/


			//商圈特殊处理:将 商圈、地域 数据合并
/*			if (tag.equals("BUSINESS_DISTRICT")){
				String busDistrictStr = stringRedisTemplate.opsForValue().get(redisKey);
				JSONObject busDistricObj = JSON.parseObject(busDistrictStr);

				if (!busDistricObj.getInteger("code").equals(0)){
					return R.failed("redis中缓存的商圈数据状态不对,code:" + busDistricObj.getInteger("code"));
				}

				String busDistricStr = busDistricObj.getJSONObject("data").getString("list");
				List<GdtTargetingTags> busDistricList = JSON.parseArray(dataStr, GdtTargetingTags.class);
				dataList.addAll(busDistricList);
			}*/

			//用户查询的id

		}
		return null;
	}

	private String getRedisKey(String accountId, String tag){
		String redisKey = null;//Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag + tag.contains("");

		switch (tag){
			case "BEHAVIOR_SYSTEMATIC" :
			case "BEHAVIOR_INDUSTRY_HOT" :
			case "INTEREST_SYSTEMATIC":
			case "INTEREST_INDUSTRY_HOT" :
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag + accountId;
				break;
			case "BEHAVIOR_CATGORY" :
			case "INTEREST_CATGORY":
			case "INTENTION" :
			case "DEVICE_BRAND_MODEL" :
			case "BUSINESS_INTEREST" :
			case "REGION":
			case "BUSINESS_DISTRICT" :
				redisKey = Constants.GDT_TARGETING_TAGS_KEY_PRIX_ + tag;
				break;
			default:
				redisKey = null;
		}
		return  redisKey;
	}

	private String fetchFromGdt(String accountId, String tag){
		HashMap<String, String> reqData = new HashMap<>();
		reqData.put("account_id", accountId);
		HashMap<String, Object> tag_spec = new HashMap<>();

		HashMap<String, Object> behavior_spec = new HashMap<>();
		if (tag.contains("BEHAVIOR"))
			tag_spec.put("behavior_spec", behavior_spec);

		HashMap<String, Object> query_spec = new HashMap<>();
		behavior_spec.put("query_spec", query_spec);

		HashMap<String, Object> interest_spec = new HashMap<>();
		if (tag.contains("INTEREST"))
			tag_spec.put("interest_spec", interest_spec);

		HashMap<String, Object> query_spec01 = new HashMap<>();
		interest_spec.put("query_spec", query_spec01);



		switch (tag){
			case "BEHAVIOR_CATGORY" :
				reqData.put("type", "BEHAVIOR");
				behavior_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_COMMON");
				break;
			case "BEHAVIOR_SYSTEMATIC" :
				reqData.put("type", "BEHAVIOR");
				behavior_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_ADVANCED_RECOMMEND");
				query_spec.put("advanced_recommend_type", "ADVANCED_RECOMMEND_TYPE_SYSTEMATIC");

				break;
			case "BEHAVIOR_INDUSTRY_HOT" :
				reqData.put("type", "BEHAVIOR");
				behavior_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_ADVANCED_RECOMMEND");
				query_spec.put("advanced_recommend_type", "ADVANCED_RECOMMEND_TYPE_INDUSTRY_HOT");
				break;

			case "INTEREST_CATGORY":
				reqData.put("type", "INTEREST");
				interest_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_COMMON");
				break;
			case "INTEREST_SYSTEMATIC":
				reqData.put("type", "INTEREST");
				interest_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_ADVANCED_RECOMMEND");
				query_spec01.put("advanced_recommend_type", "ADVANCED_RECOMMEND_TYPE_SYSTEMATIC");
				break;
			case "INTEREST_INDUSTRY_HOT" :
				reqData.put("type", "INTEREST");
				interest_spec.put("query_mode", "TARGETING_TAG_QUERY_MODE_ADVANCED_RECOMMEND");
				query_spec01.put("advanced_recommend_type", "ADVANCED_RECOMMEND_TYPE_INDUSTRY_HOT");
				break;

			case "INTENTION" :
				reqData.put("type", "INTENTION");
				break;
			case "DEVICE_BRAND_MODEL" :
				reqData.put("type", "DEVICE_BRAND_MODEL");
				tag_spec = null;
				break;
			default:
				return null;
		}

		if (tag_spec != null)
			reqData.put("tag_spec" , JSON.toJSONString(tag_spec));


		String url = "https://api.e.qq.com/v1.3/targeting_tags/get" + getUrlTail(accountId) + "&" + MapUtils.queryString(reqData);
		String resultStr = OEHttpUtils.doGdtGet(url, null);

		return resultStr;
	}

	private String getUrlTail(String accountId){

		//任意去一个 accountId去拿token
		Map<String, String> map = gdtAccesstokenService.fetchAccesstoken(accountId);
		String gdtToken = map.get("access_token");

		//String gdtToken = "4b7eff592ce3abcd4960b378674e6595";

		int nonce = RandomUtils.nextInt();
		long tsp = System.currentTimeMillis() / 1000;
		String tail = String.format("?access_token=%s&timestamp=%d&nonce=%d", gdtToken, tsp, nonce);
		return tail;
	}

	private String fileContentByName(String fileName){
		InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName);
		byte[] getData = new byte[0];
		try {
			getData = readInputStream(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String content = new String(getData);
		return content;
	}


	private static  byte[] readInputStream(InputStream inputStream) throws IOException {
		byte[] buffer = new byte[1024];
		int len = 0;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while((len = inputStream.read(buffer)) != -1) {
			bos.write(buffer, 0, len);
		}
		bos.close();
		return bos.toByteArray();
	}


	private List<GdtTargetingTags> dealLevels(List<GdtTargetingTags> arr){
		List<GdtTargetingTags> result = new ArrayList<>();

		arr.stream()
				.filter(item -> item.getParent_id().equals(BigInteger.valueOf(0)))
				.forEach(item -> {
					result.add(item);
					arr.stream()
							.filter(jtem -> (jtem.getParent_id().equals(item.getId())) && !jtem.getId().equals(BigInteger.ZERO))
							.forEach(jtem -> {
								item.getChildren().add(jtem);

								arr.stream()
										.filter(ktem -> ktem.getParent_id().equals(jtem.getId()))
										.forEach(ktem -> {
											jtem.getChildren().add(ktem);

											arr.stream()
													.filter(ltem -> ltem.getParent_id().equals(ktem.getId()))
													.forEach(ltem -> {
														ktem.getChildren().add(ltem);
													});
										});
							});
				});


		return result;
	}
}
